package engine.gameObject.collider;

import engine.gameObject.GameObject;
import engine.gameObject.terrain.Terrain;

public class TerrainCollider extends Collider {

	private Terrain terrain;
	
	public TerrainCollider(Terrain terrain) {
		this.terrain = terrain;
	}
	
	@Override
	public boolean collides(GameObject g1, GameObject g2) {
		float[] up = new float[]{0, 1, 0};
		//TODO float[] up = terrain.getRotation().getUpVector();
		//TODO consider the position, rotation and scale of the terrain. 
		float a = -(up[0] * terrain.getPosX() + up[1] * terrain.getPosY() + up[2] * terrain.getPosZ());
		
		float aboveFrac = up[0] * g2.getPosX() + up[1] * g2.getPosY() + up[2] * g2.getPosZ() + a;
		float belowFrac = (float)Math.sqrt(up[0] * up[0] + up[1] * up[1] + up[2] * up[2]);
		float distanceSpherePlane = aboveFrac / belowFrac;
		
		float lambda = -(g2.getPosX() + g2.getPosY() + g2.getPosZ() + a) / (up[0] + up[1] + up[2]);
		float x = g2.getPosX() + lambda * up[0];
		float z = g2.getPosZ() + lambda * up[2];
		
		float height = terrain.heightAt(x, z);
		
		if(distanceSpherePlane - g2.getSurroundingBoundRadius() < height && distanceSpherePlane + g2.getSurroundingBoundRadius() > height) {
			float distance = distanceSpherePlane - height;
			if(distance >= 0) {
				distance = g2.getSurroundingBoundRadius() - distance;
				
				collision(distance, new float[]{up[0] * distance, up[1] * distance, up[2] * distance}, g2);
			} else {
				distance = - g2.getSurroundingBoundRadius() - distance; 
				
				collision(distance, new float[]{up[0] * distance, up[1] * distance, up[2] * distance}, g2);
			}
			
			return true;
		}
		
		return false;
	}
	
	private void collision(float distance, float[] vector, GameObject other) {
		if(terrain.isTrigger()) {
			terrain.triggered(other, new float[]{-vector[0], -vector[1] , -vector[2]});
		} else if(other.isTrigger()) {
			other.triggered(terrain, vector);
		} else {
			other.collidesAbs(terrain, vector);
			terrain.collidesAbs(other, new float[]{-vector[0], -vector[1] , -vector[2]});
		}
	}
	
	@Override
	public Collider copy() {
		return null;
	}
	
	@Override
	public void reset() {
		//do nothing
	}
}
